/**
*******************************************************************************
* @file                  zynq_gpio.h
* @author                $Author: Xu <> $
*
* Base class for devices connected via SPI.
* Copyright 2016 RobSense. All rights reserved.
*******************************************************************************/
#ifndef _DY_HAL_
#define _DY_HAL_
#ifdef __cplusplus
extern "C" {
#endif
/***************************** Include Files *********************************/
#include "bsp.h"
#include "system.h"
#include "GPIO.h"
#include "UARTDriver.h"

#include "stdio.h"
#include "stdbool.h"
#include "stdint.h"

/************************** Constant Definitions *****************************/

/************************** Variable Definitions ******************************/
typedef void(*Proc)(void);
typedef void* PeriodicHandle;

enum BusType {
    BUS_TYPE_UNKNOWN = 0,
    BUS_TYPE_I2C     = 1,
    BUS_TYPE_SPI     = 2,
    BUS_TYPE_UAVCAN  = 3
};

enum Speed {
    SPEED_HIGH,
    SPEED_LOW,
};

typedef struct _callback_info{
    struct _callback_info *next;
    Proc cb;
    uint32_t period_usec;
    uint64_t next_usec;
} callback_info;

typedef struct {
	void (*Semaphore_init)();
	bool (*give)();
	bool (*take)(uint32_t timeout_ms);
	bool (*take_nonblocking)();
}Semaphores_t;



//typedef struct {

//}AnalogIn_t;


typedef struct {
	void (*RCInput_init)();
	bool  (*new_input)();
	uint8_t (*num_channels)();
	uint16_t (*read_single)(uint8_t ch);
	uint8_t (*read)(uint16_t* periods, uint8_t len);
	bool (*set_overrides)(int16_t *overrides, uint8_t len);
	bool (*set_override)(uint8_t channel, int16_t override);
	void (*clear_overrides)();
	void (*timer_tick)(void);
}RCInput_t;

typedef struct {
	void     (*RCOutput_init)();
	void     (*set_freq)(uint32_t chmask, uint16_t freq_hz);
	uint16_t (*get_freq)(uint8_t ch);
	void     (*enable_ch)(uint8_t ch);
	void     (*disable_ch)(uint8_t ch);
	void     (*write)(uint8_t ch, uint16_t period_us);
	uint16_t (*read_single_)(uint8_t ch);
	void     (*read_)(uint16_t* period_us, uint8_t len);
	void     (*cork)(void);
	void     (*push)(void);
}RCOutput_t;

typedef struct {
    void (*init)();
    void (*delay)(uint16_t ms);
    void (*delay_microseconds)(uint16_t us);
    void (*delay_microseconds_boost)(uint16_t us);
    void (*register_delay_callback)(Proc,uint16_t min_time_ms);
    void (*register_timer_process)(Proc);
    void (*register_io_process)(Proc);
    void (*suspend_timer_procs)();
    void (*resume_timer_procs)();
    bool (*in_timerprocess)();
    void (*register_timer_failsafe)(Proc, uint32_t period_us);
    void (*system_initialized)();
    void (*reboot)(bool hold_in_bootloader);
    void (*hal_initialized)();
}Scheduler_t;

struct SPIDesc {
    const char *name;
    uint16_t bus;
    uint8_t mode;
    uint8_t bits_per_word;
    int16_t cs_pin;
    uint32_t lowspeed;
    uint32_t highspeed;
	GPIO_TypeDef* port;
};

typedef struct _SPIDevice_t{
	void (*init)(struct _SPIDevice_t *dev);
	bool (*set_speed)(struct _SPIDevice_t dev, enum Speed speed);
	bool (*transfer)(struct _SPIDevice_t dev, const uint8_t *send, uint32_t send_len,uint8_t *recv, uint32_t recv_len);
	bool (*transfer_fullduplex)(struct _SPIDevice_t dev, const uint8_t *send, uint8_t *recv,uint32_t len);
	PeriodicHandle (*register_periodic_callback)(uint32_t period_usec, Proc cb);
	bool (*adjust_periodic_callback)(PeriodicHandle h, uint32_t period_usec);
	const char *_name;
    uint16_t _bus;
    uint8_t _mode;
    uint8_t _bits_per_word;
    int16_t _cs_pin;
    uint32_t _lowspeed;
    uint32_t _highspeed;
//    perf_counter_t perf;
    char *pname;
	GPIO_TypeDef* _cs_port;
}SPIDevice_t;

typedef struct {
	SPIDevice_t (*get_device)(const char *name);
}SPIDeviceManager_t;


//typedef struct {

//}Storage_t;




typedef struct {
	void (*set_system_clock)(uint64_t time_utc_usec);
	bool (*get_system_id)(char buf[40]);
	uint32_t (*available_memory)(void);
//	perf_counter_t (*perf_alloc)(enum perf_counter_type t, const char *name);
//	void (*perf_begin)(perf_counter_t h);
//	void (*perf_end)(perf_counter_t h);
//	void (*perf_count)(perf_counter_t h);
}Util_t;

typedef struct {
	void(*init)();
	GPIO_t GPIO;
//	AnalogIn_t AnalogIn;
	// I2CDeviceManager_t i2c_mgr;
	// RCInput_t RCInput;
	// RCOutput_t RCOutput;
	// Scheduler_t Scheduler;
	// Semaphores_t Semaphores;
	// SPIDeviceManager_t spi_mgr;
//	Storage_t Storage;
	system_t system;
	UARTDriver_t UARTDriver;
	// Util_t Util;
}DY_HAL;


// extern I2CDevice_t  MPU6050,MPU9250;
// extern SPIDevice_t  AS5048A_PITCH,AS5048A_YAW;

/************************** Function Prototypes ******************************/
void HAL_constructs(DY_HAL *instance);
void hal_dy_set_priority(uint8_t priority);
#ifdef __cplusplus
}
#endif
#endif
